﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SQLite;
using System.IO;
using System.Reflection;

namespace MOJsdk
{
    public class MojPlugin : IEquatable<MojPlugin>
    {
        [PrimaryKey]
        public string PluginName { get; set; }
        public bool IsActivated { get; set; }

        [Ignore]
        public IPlugIn Plugin { get; set; }
        [Ignore]
        public string PluginPath { get; set; }
        public bool Equals(MojPlugin p)
        { return PluginName == p.PluginName; }
    }
    public class MojPluginPool : SQLiteConnection
    {
        List<MojPlugin> _plugins;

        public MojPluginPool()
            : base(Path.Combine(MojFoldersEnum.DatabaseFolder.Value(), "Plugins"))
        {
            CreateTable<MojPlugin>();
            _plugins = new List<MojPlugin>();
            OnPluginUpdate += delegate { };
            CheckPlugins();
        }

        public void CheckPlugins()
        {
            _plugins.Clear();

            string[] paths = Directory.GetFiles(MojFoldersEnum.PluginsFolder.Value(), "*.dll", SearchOption.TopDirectoryOnly);
            foreach (var v in paths)
            {
                IPlugIn p = MojPluginPool.GetPlugin(v);
                if (p == null) continue;

                    if (Table<MojPlugin>().Count(z => z.PluginName == p.PluginName) > 0)
                    {
                        MojPlugin mp = Get<MojPlugin>(p.PluginName);
                        mp.Plugin = p;
                        mp.PluginPath = v;
                        _plugins.Add(mp);
                    }
                    else
                    {
                        MojPlugin mp = new MojPlugin()
                        {
                            Plugin = p,
                            PluginPath = v,
                            PluginName = p.PluginName,
                            IsActivated = true,
                        };
                        Insert(mp);
                        mp.Plugin.Install();
                        _plugins.Add(mp);
                    }
            }

            OnPluginUpdate(this);
        }
        public void ChangeActiveStatus(MojPlugin plugin)
        {
            plugin.IsActivated = !plugin.IsActivated;
            Update(plugin);

            if (plugin.IsActivated)
                plugin.Plugin.Inicialize();
            else
                plugin.Plugin.Dispose();

            CheckPlugins();
        }
        public MojPlugin this[string PluginName]
        {
            get { return Get<MojPlugin>(PluginName); }
        }
        public List<MojPlugin> Plugins
        { get { return _plugins; } }

        public void IniPlugins()
        {
                foreach (var p in _plugins)
                    if (p.IsActivated)
                    {
                        try
                        {
                            p.Plugin.Inicialize();
                        }
                        catch (Exception ex)
                        {
                            MojHost.GetHost.ReportError(new ErrorReporter()
                            {
                                ErrorCode = "MojPluginPool.IniPlugins",
                                ErrorDetails = ex.ToString(),
                                ErrorMessage = "Error starting plugin",
                            });
                        }
                    }
        }
        public void DisposePlugins()
        {
            foreach (var p in _plugins)
                if (p.IsActivated)
                {
                    try
                    {
                        p.Plugin.Dispose();
                    }
                    catch (Exception ex)
                    {
                        MojHost.GetHost.ReportError(new ErrorReporter()
                        {
                            ErrorCode = "MojPluginPool.IniPlugins",
                            ErrorDetails = ex.ToString(),
                            ErrorMessage = "Error starting plugin",
                        });
                    }
                }
        }

        public static IPlugIn GetPlugin(string PATH)
        {
            if (!File.Exists(PATH))
                return null;


            try
            {
                Assembly ass = Assembly.LoadFile(PATH);
                foreach (Type t in ass.GetExportedTypes())
                    if (t.GetInterface("IPlugIn") != null)
                        return Activator.CreateInstance(t) as IPlugIn;

                return null;
            }
            catch
            {
                return null;
            }
        }

        public event CallEventHandler OnPluginUpdate;
    }
}
